home *** CD-ROM | disk | FTP | other *** search
- /* HyperCard XFCN that returns the M index key items found beginning at
- * key record number N in (already opened) key file F ... called as:
- * getKeys ( M, N, F)
- * where N is 0-based, and F is a refNum value returned by
- * the XFCN openFile() ....
- *
- * The results are returned as a nice printable string consisting of M
- * repetitions of:
- * the number of occurrences of the item, ranging from 1 up to at
- * most 999999 (MAX_DIGITS long ... 6 is a nice choice), followed by;
- * a space, to separate the columns, followed by;
- * the item's key word, KEY_LENGTH characters long, padded on the right
- * by trailing blanks as necessary, followed by;
- * a <return>.
- * If there has been a mistake, a null string is returned and the function
- * also emits a beep....
- *
- * Function is stored as XFCN number 270, named "getKeys"....
- *
- * The key file must in the standard ^z browser format as created
- * by qndxr....
- *
- * 871126 ^z
- */
-
- #include <MacTypes.h>
- #include <FileMgr.h>
- #include <OSUtil.h>
- #include <HyperXCmd.h>
- #include <proto.h>
-
- #define KEY_LENGTH 28 /* depends on how index file was built */
- #define MAX_DIGITS 6 /* chosen field width for counts */
- #define MAX_COUNT 999999 /* biggest decimal number in MAX_DIGITS */
- typedef struct
- {
- char kkey[KEY_LENGTH];
- long ccount;
- } KEY_REC;
-
-
- pascal void main (XCmdBlockPtr paramPtr);
- void getKeyRec (KEY_REC *recp, long recNum, int refNum);
- void buildAnswer (char *ans, long count, char *key);
- void storeNum (char *ans, long count);
- void complain (XCmdBlockPtr paramPtr);
-
-
- pascal void main (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- KEY_REC this_rec, prev_rec;
- int refNum0, keys, i;
- long indexRecNum;
- Handle answer;
-
- if (paramPtr->paramCount != 3)
- {
- complain(paramPtr);
- return;
- }
-
- keys = atol (*(paramPtr->params[0]));
- indexRecNum = atol (*(paramPtr->params[1]));
- refNum0 = atol (*(paramPtr->params[2]));
-
- if (indexRecNum < 0 || refNum0 == 0)
- {
- complain (paramPtr);
- return;
- }
-
- answer = NewHandle (keys * (MAX_DIGITS + KEY_LENGTH + 2) + 1);
- getKeyRec (&prev_rec, indexRecNum - 1, refNum0);
-
- for (i = 0; i < keys; ++i)
- {
- getKeyRec (&this_rec, indexRecNum++, refNum0);
- buildAnswer (*answer + i * (MAX_DIGITS + KEY_LENGTH + 2),
- this_rec.ccount - prev_rec.ccount, this_rec.kkey);
- prev_rec.ccount = this_rec.ccount;
- }
-
- *(*answer + keys * (MAX_DIGITS + KEY_LENGTH + 2)) = '\0';
- paramPtr->returnValue = answer;
- return;
- }
-
-
- /* function to fetch the requested index record from the file ...
- * note that if an illegal recNum is asked for, it
- * returns 0 for ccount and a blank kkey....
- */
-
- void getKeyRec (recp, recordNum, refNum)
- KEY_REC *recp;
- long recordNum;
- int refNum;
- {
- long count;
- int i;
-
- count = sizeof(KEY_REC);
-
- if (recordNum < 0 ||
- SetFPos (refNum, fsFromStart,
- recordNum * sizeof(KEY_REC)) != noErr ||
- FSRead (refNum, &count, recp) != noErr)
- {
- for (i = 0; i < KEY_LENGTH; ++i)
- recp->kkey[i] = ' ';
- recp->ccount = 0;
- }
-
- return;
- }
-
-
- /* function to format the index record nicely as a string ....
- * put the count in its proper place (signal an overflow by
- * filling its field with stars), followed by a space, then
- * the key word itself, followed by a <return>....
- */
-
- void buildAnswer (ans, count, key)
- register char *ans, *key;
- long count;
- {
- register int i;
-
- if (count > MAX_COUNT)
- for (i = MAX_DIGITS; i > 0; --i)
- *ans++ = '*';
- else
- {
- storeNum (ans, count);
- ans += MAX_DIGITS;
- }
-
- *ans++ = ' ';
-
- for (i = KEY_LENGTH; i > 0; --i)
- *ans++ = *key++;
-
- *ans = '\r';
-
- return;
- }
-
-
- /* function to convert a number into a string of width MAX_DIGITS and
- * store it right-justified, blank-filled on left; assume that the
- * number is non-negative and is less than or equal to MAX_DIGITS
- * long in decimal.... based on K&R p. 60 example of itoa()....
- */
-
- void storeNum (ans, count)
- register char *ans;
- register long count;
- {
- register int i;
-
- i = MAX_DIGITS - 1;
-
- do
- ans[i--] = count % 10 + '0';
- while ((count /= 10) > 0);
-
- for ( ; i >= 0; --i)
- ans[i] = ' ';
-
- return;
- }
-
-
- /* function to beep and set the return string to null (= "")
- */
-
- void complain (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Handle answer;
-
- SysBeep (10);
- answer = NewHandle (1);
- **answer = '\0';
- paramPtr->returnValue = answer;
- return;
- }
-
-
-
- /* function to convert alphabetic string to a long integer ... from LSC
- * library.... simplified to avoid using isspace() & isdigit() .... */
-
- long atol (s)
- register char *s;
- {
- register char signflag = 0;
- register long r = 0;
-
- while ((*s == ' '))
- s++;
-
- if (*s == '-')
- {
- signflag = 1;
- s++;
- }
- else if (*s == '+')
- s++;
-
- while (*s >= '0' && *s <= '9')
- r = r * 10 + (*s++ - '0');
-
- return (signflag ? -r : r);
- }
-
-